package org.jeecg.modules.bicycle.order.service.impl;

import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;

import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.approve.free.entity.BikeApproveFreeCharge;
import org.jeecg.modules.approve.free.mapper.BikeApproveFreeChargeMapper;
import org.jeecg.modules.approve.refund.entity.BikeApproveReturn;
import org.jeecg.modules.approve.refund.mapper.BikeApproveReturnMapper;
import org.jeecg.modules.bicycle.order.entity.BikeVehicleOrder;
import org.jeecg.modules.bicycle.order.mapper.BikeVehicleOrderMapper;
import org.jeecg.modules.bicycle.order.service.IBikeVehicleOrderService;
import org.jeecg.modules.bicycle.order.vo.BikeVehicleOrderByIdRes;
import org.jeecg.modules.bicycle.order.vo.BikeVehicleOrderRes;
import org.jeecg.modules.bicycle.order.vo.IsFree;
import org.jeecg.modules.bicycle.order.vo.Refund;
import org.jeecg.modules.bicycle.vehicle.entity.BikeVehicle;
import org.jeecg.modules.bicycle.vehicle.mapper.BikeVehicleMapper;
import org.jeecg.modules.common.service.CommonMethodService;
import org.jeecg.modules.constant.BikeConstant;
import org.jeecg.modules.param.member.entity.BikeMemberUser;
import org.jeecg.modules.param.member.mapper.BikeMemberUserMapper;
import org.jeecg.modules.param.refund.entity.BikeMemberUserReturn;
import org.jeecg.modules.param.refund.mapper.BikeMemberUserReturnMapper;
import org.jeecg.modules.param.spend.entity.BikeMemberUserSpend;
import org.jeecg.modules.param.spend.mapper.BikeMemberUserSpendMapper;
import org.jeecg.modules.param.station.mapper.BikeStationMapper;
import org.jeecg.modules.param.station.vo.SysUserRe;
import org.jeecg.modules.system.Device.DeviceMethod;
import org.jeecg.modules.utils.AliPayKit;
import org.jeecg.modules.utils.CostUtils;
import org.jeecg.modules.utils.ExcelUtils;
import org.jeecg.modules.utils.page.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.ElementType;
import java.math.BigDecimal;
import java.util.*;

/**
 * @Description: 借车记录
 * @Author: 月月鸟
 * @Date:   2021-05-28
 * @Version: V1.0
 */
@Service
public class BikeVehicleOrderServiceImpl extends ServiceImpl<BikeVehicleOrderMapper, BikeVehicleOrder> implements IBikeVehicleOrderService {
    @Resource
    private BikeVehicleOrderMapper bikeVehicleOrderMapper;
    @Resource
    private BikeMemberUserSpendMapper bikeMemberUserSpendMapper;
    @Resource
    private BikeMemberUserMapper bikeMemberUserMapper;
    @Resource
    private BikeMemberUserReturnMapper bikeMemberUserReturnMapper;
    @Resource
    private BikeApproveFreeChargeMapper bikeApproveFreeChargeMapper;
    @Resource
    private BikeApproveReturnMapper bikeApproveReturnMapper;
    @Resource
    private BikeStationMapper bikeStationMapper;
    @Resource
    private DeviceMethod deviceMethod;
    @Autowired
    private CommonMethodService commonMethodService ;
    @Resource
    private BikeVehicleMapper bikeVehicleMapper;
    @Override
    public Result<?> stopTime(BikeVehicleOrderRes bikeVehicleOrderRes) {
        if (bikeVehicleOrderRes.getId()==null){
            return Result.error("请选择用户");
        }
        BikeVehicleOrder data = bikeVehicleOrderMapper.selectById(bikeVehicleOrderRes.getId());
        if (data.getStopTime()!=null){
            return Result.error("用户计费已经停止！");
        }else {
            //判断 停止计费时间，必须大于借车时间
            if (bikeVehicleOrderRes.getStopTime().getTime()<=data.getPickTime().getTime()){
                return Result.error("停止计费时间不能在借车之前！");
            }
            //停止计费时间
            data.setStopTime(bikeVehicleOrderRes.getStopTime());
            //使用时长
            long second = CostUtils.getSecond(data.getPickTime().getTime(), data.getStopTime().getTime());
            data.setUseLong((int) second);
            //应付
            BigDecimal cost = new BigDecimal(commonMethodService.getCost(data.getPickTime(), data.getStopTime()));
            data.setPayCost(cost);
            //是手动停止计费
            data.setIsStop("1");
        }
        bikeVehicleOrderMapper.updateById(data);
        return Result.OK("已停止计费！");
    }
    /**
     * 后台手工还车
     * */
    @Override
    public Result<?> stopTimeCost(String id) {
        if (id==null){
            return Result.error("请选择用户");
        }
        BikeVehicleOrder data = bikeVehicleOrderMapper.selectById(id);
        BikeMemberUser memberUser = bikeMemberUserMapper.selectById(data.getPickUser());
        BikeVehicle vehicle = bikeVehicleMapper.selectById(data.getVehicleId());
        if (data.getParkTime()!=null){
            return Result.error("记录已还车，无需手动还车");
        }
        //判断是否停止计费
        if (data.getStopTime() == null) {
            //停止计费时间
            data.setStopTime(new Date());
            //是手动停止计费
            data.setIsStop("1");
        }
        data.setParkTime(new Date());
        //使用时长
        long second = CostUtils.getSecond(data.getPickTime().getTime(), data.getStopTime().getTime());
        data.setUseLong((int) second);
        //应付
        BigDecimal cost = new BigDecimal(commonMethodService.getCost(data.getPickTime(),data.getStopTime()));
        data.setPayCost(cost);
        data.setRideStatus("4");
        //还车类型 后台还车
        LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal();
        data.setParkUser(sysUser.getId());
        data.setParkType("3");
        //订单金额等于0
        if (cost.compareTo(new BigDecimal(0))==0){
            data.setIsPay(BikeConstant.y_n_yes);
            data.setPayActual(new BigDecimal(0));
            data.setRideStatus("5");
        }
        //修改订单状态
        bikeVehicleOrderMapper.updateById(data);
        //修改车辆状态为维修中
        vehicle.setStatus("6");
        bikeVehicleMapper.updateById(vehicle);
        //新增用户消息
        String sms = addSmsParam(commonMethodService.getMessageTemplateByCode(BikeConstant.park_bike_sms_code),second*1000,cost);
        commonMethodService.addSysMessages(memberUser.getId(),memberUser.getCode(),"还车提醒",sms);
        //deviceMethod.lockSocketOpenYN(BikeConstant.y_n_yes, "a","b", "c", memberUser.getCode(), 4);

        return Result.OK("还车成功！");
    }
    /**
     *  将 用车时长，金额导入到短信模板
     * @param
     * */
    private String addSmsParam(String smsTemplate, long useTime, BigDecimal bigDecimal) {
        String replace = smsTemplate
                .replace("{时长}", CostUtils.NewHHmm(useTime))
                .replace("{金额}", bigDecimal.toString());
        return replace;
    }
    @Override
    public Result<?> pageList(Integer pageNo, Integer pageSize, BikeVehicleOrderRes bikeVehicleOrderRes) {
        Page<BikeVehicleOrderRes> page = new Page<>(pageNo, pageSize);
        page.setOptimizeCountSql(true);
        if (StringUtils.isNotEmpty(bikeVehicleOrderRes.getPickIdCard())){
            bikeVehicleOrderRes.setPickIdCard(bikeVehicleOrderRes.getPickIdCard().replace("x","X"));
        }
        if (StringUtils.isNotEmpty(bikeVehicleOrderRes.getTimeSelection())){
            bikeVehicleOrderRes.setPickTime(new Date(new Date().getTime()-86400000));
        }
        Page<BikeVehicleOrderRes> bikeVehicleOrderResIPage = bikeVehicleOrderMapper.pageList(page,bikeVehicleOrderRes);
        List<BikeVehicleOrderRes> records = bikeVehicleOrderResIPage.getRecords();
        if (!records.isEmpty()){
            for (BikeVehicleOrderRes tb : records){
                //用车时长转为mm:ss格式
                if (tb.getUseLong()!=null){
                    tb.setUseMMss(CostUtils.MMss(tb.getUseLong()));
                }
            }
        }
        PageInfo pageInfo = new PageInfo();
        pageInfo.setCurrent(bikeVehicleOrderResIPage.getCurrent());
        pageInfo.setRecords(records);
        pageInfo.setTotal(bikeVehicleOrderResIPage.getTotal());
        pageInfo.setSize(bikeVehicleOrderResIPage.getSize());
        return Result.OK(pageInfo);
    }


    @Override
    public Result<?> pageListById(String id) {
        BikeVehicleOrderByIdRes bikeVehicleOrderByIdRes = bikeVehicleOrderMapper.pageListById(id);
        if (bikeVehicleOrderByIdRes!=null){
            //用车时长转为mm:ss格式
            if (StringUtils.isNotEmpty(bikeVehicleOrderByIdRes.getUseLong().toString())){
                bikeVehicleOrderByIdRes.setUseMMss(CostUtils.MMss(bikeVehicleOrderByIdRes.getUseLong()));
            }
            //根据 还车类型，查询还车人
            if (StringUtils.isNotEmpty(bikeVehicleOrderByIdRes.getParkType())){
                if (bikeVehicleOrderByIdRes.getParkType().equals("1")){
                    bikeVehicleOrderByIdRes.setParkUserName(bikeVehicleOrderByIdRes.getPickUserName());
                }else {
                    SysUserRe sysUserRe = bikeStationMapper.selectAdmin(bikeVehicleOrderByIdRes.getParkUser());
                    if (sysUserRe!=null){
                        bikeVehicleOrderByIdRes.setParkUserName(sysUserRe.getRealname());
                    }
                }
            }
        }
        return Result.OK(bikeVehicleOrderByIdRes);
    }

    @Override
    public ModelAndView exportXls(HttpServletRequest request, BikeVehicleOrderRes bikeVehicleOrderRes) {
        List<BikeVehicleOrderRes> bikeVehicleOrderResList = bikeVehicleOrderMapper.list(bikeVehicleOrderRes);
        for (BikeVehicleOrderRes tb : bikeVehicleOrderResList){
            //用车时长转为mm:ss格式
            if (tb.getUseLong()!=null){
                tb.setUseMMss(CostUtils.MMss(tb.getUseLong()));
            }
        }
        return ExcelUtils.exportXls(request,bikeVehicleOrderResList,BikeVehicleOrderRes.class,"借还记录表");
    }

    public Result<?> refund(Refund refund) {
        Map<String, String> params = null;
        //查询消费记录 根据借车记录 id
        QueryWrapper<BikeMemberUserSpend> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",refund.getId());
        BikeMemberUserSpend bikeMemberUserSpend = bikeMemberUserSpendMapper.selectOne(wrapper);

        //退款记录
        BikeMemberUserReturn bikeMemberUserReturn = new BikeMemberUserReturn();

        //会员信息
        BikeMemberUser memberUserData = bikeMemberUserMapper.selectById(bikeMemberUserSpend.getUserId());
        //支付宝退款编码
        String outRequestNo = UUID.randomUUID().toString();

        //钱包退款
        if (bikeMemberUserSpend.getSpendType().equals("1")){
            int i = refund.getRefundAmount().compareTo(bikeMemberUserSpend.getSpendAmount());
            if (i == 1){
                return Result.error("退款金额大于订单金额");
            }
            BikeMemberUser memberUser = new BikeMemberUser();
            //会员信息表 id
            memberUser.setId(memberUserData.getId());
            //会员信息表 余额
            memberUser.setBalance(memberUserData.getBalance().add(refund.getRefundAmount()));
            //修改余额
            bikeMemberUserMapper.updateById(memberUser);
            //退款记录
            //借车订单
            bikeMemberUserReturn.setOrderId(bikeMemberUserSpend.getOrderId());
            //用户
            bikeMemberUserReturn.setUserId(bikeMemberUserSpend.getUserId());
            //钱包退款金额
            bikeMemberUserReturn.setReturnAmount(refund.getRefundAmount());
            //退款后余额
            bikeMemberUserReturn.setBalanceEnd(memberUserData.getBalance().add(refund.getRefundAmount()));

            //退款类型 1 钱包 2 支付宝 3 组合
            bikeMemberUserReturn.setReturnType("1");
            //退款原因备注
            bikeMemberUserReturn.setMemo(refund.getRefundReason());
            bikeMemberUserReturnMapper.insert(bikeMemberUserReturn);
            return Result.OK("余额退款成功");
        }
        //支付宝支付退支付宝
        if (bikeMemberUserSpend.getSpendType().equals("2")){
            int i = refund.getRefundAmount().compareTo(bikeMemberUserSpend.getAliAmount());
            if (i == 1){
                return Result.error("退款金额大于订单金额");
            }
            //商户订单号
            params.put("outTradeNo",bikeMemberUserSpend.getOutTradeNo());
            //退款金额
            params.put("refundAmount",refund.getRefundAmount().toString());
            //退款原因
            params.put("refundReason",refund.getRefundReason());
            //退款请求有号
            params.put("outRequestNo",outRequestNo);
            AlipayTradeRefundResponse ali = AliPayKit.refund(params);
            //如果状态码为 10000 则为退款成功
            if (ali.getCode().equals("10000")){
                //退款记录
                //借车订单
                bikeMemberUserReturn.setOrderId(bikeMemberUserSpend.getOrderId());
                //用户
                bikeMemberUserReturn.setUserId(bikeMemberUserSpend.getUserId());
                //退款后余额
                bikeMemberUserReturn.setBalanceEnd(memberUserData.getBalance());
                //支付宝退款金额
                bikeMemberUserReturn.setAliAmount(refund.getRefundAmount());
                //退款类型 1 钱包 2 支付宝 3 组合
                bikeMemberUserReturn.setReturnType("2");
                //映射支付宝用户
                bikeMemberUserReturn.setAliUserId(bikeMemberUserSpend.getAliUserId());
                //映射支付宝订单编号
                bikeMemberUserReturn.setAliOrderId(bikeMemberUserSpend.getAliOrderId());
                //支付宝退款编号
                bikeMemberUserReturn.setAliRefundId(outRequestNo);
                //退款原因备注
                bikeMemberUserReturn.setMemo(refund.getRefundReason());
                bikeMemberUserReturnMapper.insert(bikeMemberUserReturn);
                return Result.OK("支付宝退款成功");
            }else{
                return Result.error(Integer.parseInt(ali.getCode()),ali.getMsg());
            }
        }
        //组合支付,各自原路退   优先支付宝
        if (bikeMemberUserSpend.getSpendType().equals("3")){
            int i = refund.getRefundAmount().compareTo(bikeMemberUserSpend.getAliAmount().add(bikeMemberUserSpend.getSpendAmount()));
            if (i == 1){
                return Result.error("退款金额大于金额");
            }
            int i1 = refund.getRefundAmount().compareTo(bikeMemberUserSpend.getAliAmount());
            //判断退款金额不大于 订单支付宝付款金额
            BikeMemberUser memberUser = new BikeMemberUser();
            //余额退款
            String returnAmount = "0";
            //支付宝退款
            String aliReturn = "0";
            if (i1 != 1){
                //全部通过支付宝退款
                //商户订单号
                params.put("outTradeNo",bikeMemberUserSpend.getOutTradeNo());
                //退款金额
                aliReturn=refund.getRefundAmount().toString();
                params.put("refundAmount",aliReturn);
                //退款原因
                params.put("refundReason",refund.getRefundReason());
                //退款请求有号
                params.put("outRequestNo",outRequestNo);
            }else {
                //支付宝部分退款
                //商户订单号
                params.put("outTradeNo",bikeMemberUserSpend.getOutTradeNo());
                //支付宝支付金额全部退款
                aliReturn=bikeMemberUserSpend.getAliAmount().toString();
                params.put("refundAmount",aliReturn);
                //退款原因
                params.put("refundReason",refund.getRefundReason());
                //退款请求有号
                params.put("outRequestNo",outRequestNo);
                //多余部分余额退款   退款金额 - 支付宝退款金额  = 余额退款金额
                returnAmount=refund.getRefundAmount().subtract(bikeMemberUserSpend.getAliAmount()).toString();
                //会员信息表 id
                memberUser.setId(memberUserData.getId());
                //会员信息表 余额
                memberUser.setBalance(memberUserData.getBalance().add(new BigDecimal(returnAmount)));
            }
            //支付宝退款接口
            AlipayTradeRefundResponse ali = AliPayKit.refund(params);
            //退款记录
            //如果状态码为 10000 则为退款成功
            if (ali.getCode().equals("10000")){
                //支付宝退款成功后，退余额
                //修改余额
                bikeMemberUserMapper.updateById(memberUser);
                //退款记录
                //借车订单
                bikeMemberUserReturn.setOrderId(bikeMemberUserSpend.getOrderId());
                //用户
                bikeMemberUserReturn.setUserId(bikeMemberUserSpend.getUserId());
                //支付宝退款金额
                bikeMemberUserReturn.setAliAmount(new BigDecimal(aliReturn));
                //余额退款金额
                bikeMemberUserReturn.setReturnAmount(new BigDecimal(returnAmount));
                //退款后余额
                bikeMemberUserReturn.setBalanceEnd(memberUser.getBalance());
                //退款类型 1 钱包 2 支付宝 3 组合
                bikeMemberUserReturn.setReturnType("3");
                //映射支付宝用户
                bikeMemberUserReturn.setAliUserId(bikeMemberUserSpend.getAliUserId());
                //映射支付宝订单编号
                bikeMemberUserReturn.setAliOrderId(bikeMemberUserSpend.getAliOrderId());
                //支付宝退款编号
                bikeMemberUserReturn.setAliRefundId(outRequestNo);
                //退款原因备注
                bikeMemberUserReturn.setMemo(refund.getRefundReason());
                bikeMemberUserReturnMapper.insert(bikeMemberUserReturn);
                return Result.OK("组合退款成功");
            }else{
                return Result.error(Integer.parseInt(ali.getCode()),ali.getMsg());
            }
        }
        return Result.OK("免单无需退款");
    }

    @Override
    public Result<?> isFree(IsFree isFree) {
        //申请人信息
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //判断免单条件
        if (StringUtils.isEmpty(isFree.getParkType())){
            return Result.error("请先还车");
        }
        Integer selectCount = bikeApproveFreeChargeMapper.selectCount(new QueryWrapper<BikeApproveFreeCharge>()
                .eq("order_id", isFree.getId())
                .ne("approve_status", "2"));
        if (selectCount!=0){
            return Result.error("请勿重复提交");
        }

        if (isFree.getBillStatus().equals("2")||isFree.getBillStatus().equals("3")){
            return Result.error("单据状态不符合免单");
        }
        if (isFree.getPayCost().compareTo(BigDecimal.valueOf(0))==0){
            return Result.error("应支付0元，无需免单");
        }
        if (isFree.getIsPay().equals(BikeConstant.y_n_yes)){
            return Result.error("已支付订单请申请退款");
        }
        //免单审批信息
        BikeApproveFreeCharge bikeApproveFreeCharge = new BikeApproveFreeCharge();
        bikeApproveFreeCharge.setOrderId(isFree.getId());//订单id
        bikeApproveFreeCharge.setApplyCause(isFree.getApply_cause());//申请理由
        bikeApproveFreeCharge.setApplyTime(new Date());//申请时间
        bikeApproveFreeCharge.setApplyBy(sysUser.getUsername());//申请人
        bikeApproveFreeCharge.setFreeAmount(isFree.getPayCost());//免单金额
        bikeApproveFreeCharge.setApproveStatus("0");//审批状态为未审批
        bikeApproveFreeChargeMapper.insert(bikeApproveFreeCharge);
        //借车订单信息
        BikeVehicleOrder bikeVehicleOrder = new BikeVehicleOrder();
        bikeVehicleOrder.setId(isFree.getId());
        bikeVehicleOrder.setBillStatus("2");
        bikeVehicleOrderMapper.updateById(bikeVehicleOrder);
        return Result.OK("已发起免单审批");
    }

    @Override
    public Result<?> isRefund(IsFree isFree) {
        //申请人信息
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //借车订单信息
        BikeVehicleOrder bikeVehicleOrder = bikeVehicleOrderMapper.selectById(isFree.getId());
        if (bikeVehicleOrder.getPayActual().compareTo(BigDecimal.valueOf(0)) < 1){
            return Result.error("实际付款0元，无需退款");
        }
        //判断退款条件
        if (isFree.getIsPay().equals(BikeConstant.y_n_no)){
            return Result.error("订单未付款");
        }
        if (isFree.getPayCost().compareTo(BigDecimal.valueOf(0)) < 1){
            return Result.error("应支付0元，无需退款");
        }
        if (isFree.getReturnCost().compareTo(BigDecimal.valueOf(0))<1){
            return Result.error("必须大于0");
        }
        if (isFree.getReturnCost().compareTo(isFree.getPayCost())==1){
            return Result.error("退款金额大于实付金额");
        }
        Integer selectCount1 = bikeApproveFreeChargeMapper.selectCount(new QueryWrapper<BikeApproveFreeCharge>()
                .ne("approve_status", "2")
                .eq("order_id", isFree.getId())
        );
        if (selectCount1!=0){
            return Result.error("有审批中的免单申请，无法重复提交！");
        }
        Integer selectCount = bikeApproveReturnMapper.selectCount(new QueryWrapper<BikeApproveReturn>()
                .eq("approve_status", "0")
                .eq("order_id",isFree.getId())
        );
        if (selectCount!=0){
            return Result.error("请勿重复提交！");
        }
        if (!isFree.getBillStatus().equals("4")){
            return Result.error("不符合退款条件！");
        }
        //退款审批信息
        BikeApproveReturn bikeApproveReturn = new BikeApproveReturn();
        bikeApproveReturn.setOrderId(isFree.getId());//订单id
        bikeApproveReturn.setApplyCause(isFree.getApply_cause());//申请理由
        bikeApproveReturn.setApplyTime(new Date());//申请时间
        bikeApproveReturn.setApplyBy(sysUser.getUsername());//申请人
        bikeApproveReturn.setFreeAmount(isFree.getReturnCost());//退款金额
        bikeApproveReturn.setApproveStatus("0");//审批状态为未审批
        bikeApproveReturnMapper.insert(bikeApproveReturn);

        bikeVehicleOrder.setBillStatus("3");
        bikeVehicleOrderMapper.updateById(bikeVehicleOrder);
        return Result.OK("已发起退款审批");
    }


}
